﻿using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Text;

namespace PickGold.Api
{
	public static class User32
	{
		public const string DLL = ApiUtil.DLL_USER32;

		/// <summary>
		/// 判断屏幕上是否存在任何弹出式窗口
		/// 对该函数来说，弹出式菜单包含所有可见的包容顶级窗口，无论弹出式还是重叠窗口
		/// </summary>
		/// <returns>如存在弹出式菜单，则返回TRUE（非零）</returns>
		[DllImport(DLL)]
		public static extern bool AnyPopup();

		/// <summary>
		/// 返回与windows环境有关的信息
		/// </summary>
		/// <param name="nIndex">常数，指定欲获取的信息：SM；</param>
		/// <returns>取决于具体的常数索引</returns>
		[DllImport(DLL)]
		public static extern int GetSystemMetrics(int nIndex);

		/// <summary>
		/// 将指定的窗口带至窗口列表顶部。倘若它部分或全部隐藏于其他窗口下面，则将隐藏的部分完全显示出来。该函数也对弹出式窗口、顶级窗口以及MDI子窗口产生作用
		/// </summary>
		/// <param name="hwnd">欲带至顶部的那个窗口的句柄</param>
		/// <returns>非零表示成功，零表示失败。会设置GetLastError</returns>
		[DllImport(DLL)]
		public static extern bool BringWindowToTop(IntPtr hwnd);

		/// <summary>
		/// 最小化指定的窗口。窗口不会从内存中清除
		/// </summary>
		/// <param name="hwnd">欲最小化的那个窗口的句柄</param>
		/// <returns>非零表示成功，零表示失败。会设置GetLastError</returns>
		[DllImport(DLL)]
		public static extern bool CloseWindow(IntPtr hwnd);

		/// <summary/>
		[DllImport(DLL)]
		public static extern bool SetCursorPos(int X, int Y);

		/// <summary/>
		[DllImport(DLL)]
		public static extern IntPtr FindWindow(string @class, string title);

		/// <summary/>
		[DllImport(DLL)]
		public static extern IntPtr FindWindowEx(HandleRef hwndParent, HandleRef hwndChildAfter, string strClass, string strWindow);
		/// <summary/>
		[DllImport(DLL)]
		public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string strClass, string strWindow);

		/// <summary>
		/// 控制窗口的可见性
		/// </summary>
		/// <param name="hWnd">窗口句柄，要向这个窗口应用由nCmdShow指定的命令</param>
		/// <param name="nCmdShow">为窗口指定可视性方面的一个命令:SW</param>
		/// <returns>如窗口之前是可见的，则返回TRUE（非零），否则返回FALSE（零）</returns>
		[DllImport(DLL)]
		public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

		/// <summary>
		/// 获得指定窗口的状态及位置信息
		/// </summary>
		/// <param name="hwnd">欲获取信息的那个窗口的句柄</param>
		/// <param name="lpwndpl">包含的窗口位置和状态信息的结构；在调用这个函数之前，请务必设置长度Length字段</param>
		/// <returns>非零表示成功，零表示失败。会设置GetLastError</returns>
		[DllImport(DLL)]
		public static extern bool GetWindowPlacement(IntPtr hwnd, ref WINDOWPLACEMENT lpwndpl);
		/// <summary>
		/// 
		/// </summary>
		/// <param name="hwnd"></param>
		/// <param name="dwTime"></param>
		/// <param name="dwFlags"><see cref="AW"/>AW</param>
		/// <returns></returns>
		[DllImport(DLL)]
		public static extern bool AnimateWindow(IntPtr hwnd, int dwTime, int dwFlags);
		/// <summary>
		/// 判断一个窗口是否为另一窗口的子或隶属窗口
		/// </summary>
		/// <param name="hWndParent">父窗口的句柄</param>
		/// <param name="hwnd">欲测试的窗口的句柄</param>
		/// <returns>非零表示成功，零表示失败</returns>
		[DllImport(DLL)]
		public static extern bool IsChild(IntPtr hWndParent, IntPtr hwnd);

		/// <summary>
		/// 判断窗口是否已最小化
		/// </summary>
		/// <param name="hwnd">待检测窗口的句柄</param>
		/// <returns>非零表示成功，零表示失败</returns>
		[DllImport(DLL)]
		public static extern bool IsIconic(IntPtr hwnd);

		/// <summary>
		/// 判断窗口是否最大化
		/// </summary>
		/// <param name="hwnd">待检测窗口的句柄</param>
		/// <returns>非零表示成功，零表示失败</returns>
		[DllImport(DLL)]
		public static extern bool IsZoomed(IntPtr hwnd);

		/// <summary>
		/// 判断一个窗口句柄是否有效
		/// 如在一个程序变量里容纳了窗口句柄，为了解它是否仍然有效，就可考虑使用这个函数
		/// </summary>
		/// <param name="hwnd">待检查窗口的句柄</param>
		/// <returns>非零表示成功，零表示失败</returns>
		[DllImport(DLL)]
		public static extern bool IsWindow(IntPtr hwnd);

		/// <summary>
		/// 判断窗口是否处于活动状态
		/// </summary>
		/// <param name="hwnd">待检测窗口的句柄</param>
		/// <returns>非零表示成功，零表示失败</returns>
		[DllImport(DLL)]
		public static extern bool IsWindowEnabled(IntPtr hwnd);

		/// <summary>
		/// 判断一个窗口是否为Unicode窗口。这意味着窗口为所有基于文本的消息都接收Unicode文字
		/// </summary>
		/// <param name="hwnd">待检测窗口的句柄</param>
		/// <returns>如是个Unicode窗口则返回非零值，如是个ANSI窗口则返回零</returns>
		[DllImport(DLL)]
		public static extern bool IsWindowUnicode(IntPtr hwnd);

		/// <summary>
		/// 判断窗口是否可见
		/// </summary>
		/// <param name="hwnd">待检测窗口的句柄</param>
		/// <returns>如窗口可见则返回TRUE（非零）</returns>
		[DllImport(DLL)]
		public static extern bool IsWindowVisible(IntPtr hwnd);

		/// <summary>
		/// 恢复一个最小化的程序，并将其激活
		/// </summary>
		/// <param name="hwnd">欲恢复的窗口</param>
		/// <returns>非零表示成功，零表示失败。会设置GetLastError</returns>
		[DllImport(DLL)]
		public static extern bool OpenIcon(IntPtr hwnd);

		/// <summary>
		/// 搜索内部窗口列表，寻找隶属于指定窗口的头一个窗口的句柄
		/// Z序列中的顶级窗口也是内部窗口列表的第一个窗口
		/// </summary>
		/// <param name="hwnd">想在其中搜寻顶级子的窗口。零表示寻找位于桌面的顶级窗口</param>
		/// <returns>位于指定窗口内部的顶级子窗口的句柄</returns>
		[DllImport(DLL)]
		public static extern IntPtr GetTopWindow(IntPtr hwnd);

		/// <summary>
		/// 获得活动窗口的句柄
		/// </summary>
		/// <returns>活动窗口的句柄，如没有窗口处于活动状态，则返回零值</returns>
		[DllImport(DLL)]
		public static extern IntPtr GetActiveWindow();

		/// <summary>
		/// 获得拥有输入焦点的窗口的句柄
		/// </summary>
		/// <returns>拥有焦点的那个窗口的句柄。如没有窗口拥有输入焦点，则返回零</returns>
		[DllImport(DLL)]
		public static extern IntPtr GetFocus();

		/// <summary>
		/// 获得前台窗口的句柄。这里的“前台窗口”是指前台应用程序的活动窗口
		/// windows nt支持多个桌面，它们相互间是独立的。每个桌面都有自己的前台窗口
		/// </summary>
		/// <returns>前台窗口的句柄</returns>
		[DllImport(DLL)]
		public static extern IntPtr GetForegroundWindow();

		/// <summary/>
		[DllImport(DLL)]
		public static extern IntPtr SetForegroundWindow(IntPtr hWnd);

		/// <summary>
		/// 切换到指定窗口，如果窗口未激活则激活，如果窗口最小化则还原。
		/// </summary>
		/// <param name="hWnd">要切换到的窗口句柄</param>
		/// <param name="fAltTab">是否激活窗口</param>
		[DllImport(DLL)]
		public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);

		/// <summary>
		/// 获得整个窗口的范围矩形，窗口的边框、标题栏、滚动条及菜单等都在这个矩形内
		/// 如将它与通过GetDesktopWindow获得的句柄联合使用，可获得对整个可视显示区域（桌面）进行说明的矩形
		/// </summary>
		/// <param name="hwnd">想获得范围矩形的那个窗口的句柄</param>
		/// <param name="rect">屏幕坐标中随同窗口装载的矩形</param>
		/// <returns>非零表示成功，零表示失败。会设置GetLastError</returns>
		[DllImport(DLL)]
		/// <summary>
		/// 获得整个窗口的范围矩形，窗口的边框、标题栏、滚动条及菜单等都在这个矩形内
		/// 如将它与通过GetDesktopWindow获得的句柄联合使用，可获得对整个可视显示区域（桌面）进行说明的矩形
		/// </summary>
		/// <param name="hwnd">想获得范围矩形的那个窗口的句柄</param>
		/// <param name="rect">屏幕坐标中随同窗口装载的矩形</param>
		/// <returns>非零表示成功，零表示失败。会设置GetLastError</returns>
		public static extern bool GetWindowRect(HandleRef hwnd, out RECT rect);
		/// <summary>
		/// 获得整个窗口的范围矩形，窗口的边框、标题栏、滚动条及菜单等都在这个矩形内
		/// 如将它与通过GetDesktopWindow获得的句柄联合使用，可获得对整个可视显示区域（桌面）进行说明的矩形
		/// </summary>
		/// <param name="hwnd">想获得范围矩形的那个窗口的句柄</param>
		/// <param name="rect">屏幕坐标中随同窗口装载的矩形</param>
		/// <returns>非零表示成功，零表示失败。会设置GetLastError</returns>
		[DllImport(DLL)]
		public static extern IntPtr GetWindowRect(IntPtr hwnd, out RECT rect);

		/// 与ShowWindow相似，只是这时的ShowWindow命令会投递到指定的窗口，然后进行异步处理。这样一来，就可控制从属于另一个进程的窗口的可视情况。同时无须担心另一个进程挂起的时候，自己的应用程序也会牵连其中返回值
		/// <param name="hWnd">窗口句柄</param>
		/// <param name="cmdShow">为窗口指定可视性方面的一个命令</param>  
		/// <returns>如窗口之前是可见的，则返回TRUE（非零），否则返回FALSE（零）</returns> 
		[DllImport(DLL)]
		public static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);

		/// <summary>
		/// 设置窗口消息钩子
		/// </summary>
		/// <param name="idHook">WH.HookType</param>
		/// <param name="lpfn"></param>
		/// <param name="hInstance"></param>
		/// <param name="threadId"></param>
		/// <returns></returns>
		[DllImport(DLL, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
		public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, IntPtr threadId);
		/// <summary>
		/// 调用下一窗口消息钩子
		/// </summary>
		/// <param name="hhk">SetWindowsHookEx 返回值</param>
		/// <param name="nCode"></param>
		/// <param name="wParam"></param>
		/// <param name="lParam"></param>
		/// <returns></returns>
		[DllImport(DLL)]
		public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
		/// <summary>
		/// 取消窗口消息钩子
		/// </summary>
		/// <param name="idHook"></param>
		/// <returns></returns>
		[DllImport(DLL, CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
		public static extern bool UnhookWindowsHookEx(int idHook);

		/// <summary>
		/// 在给定一种窗口样式的前提下，计算获得目标客户区矩形所需的窗口大小
		/// 先用GetWindowLong取得一个窗体的样式。如菜单占用两行以上的空间，则函数不能正确计算大小。如程序使用了多行标题，则应使用GetSystemMetrics
		/// </summary>
		/// <param name="lpRect">最初包含要求的客户区。由函数设为目标窗口矩形大小</param>
		/// <param name="dwStyle">窗口样式；在调用本函数前，先用GetWindowLong取得一个窗体的样式。如菜单占用两行以上的空间，则函数不能正确计算大小。如程序使用了多行标题，则应使用GetSystemMetrics</param>
		/// <param name="bMenu">如窗口有菜单，则设为TRUE（非零）</param>
		/// <returns>如执行成功，则返回非零值；如失败，返回零值。会设置GetLastError</returns>
		[DllImport(DLL)]
		public static extern bool AdjustWindowRect(ref RECT lpRect, int dwStyle, int bMenu);
		/// <summary>
		/// 在给定一种窗口样式的前提下，计算获得目标客户区矩形所需的窗口大小
		/// 先用GetWindowLong取得一个窗体的样式。如菜单占用两行以上的空间，则函数不能正确计算大小。如程序使用了多行标题，则应使用GetSystemMetrics
		/// </summary>
		/// <param name="lpRect">最初包含要求的客户区。由函数设为目标窗口矩形大小</param>
		/// <param name="dwStyle">窗口样式；在调用本函数前，先用GetWindowLong取得一个窗体的样式。如菜单占用两行以上的空间，则函数不能正确计算大小。如程序使用了多行标题，则应使用GetSystemMetrics</param>
		/// <param name="bMenu">如窗口有菜单，则设为TRUE（非零）</param>
		/// <param name="dwEsStyle">扩展窗口样式（只适用于AdjustWindowRectEx）</param>
		/// <returns>如执行成功，则返回非零值；如失败，返回零值。会设置GetLastError</returns>
		[DllImport(DLL)]
		public static extern bool AdjustWindowRectEx(ref RECT lpRect, int dwStyle, int bMenu, int dwEsStyle);

		/// <summary>
		/// 从指定窗口的结构中取得信息
		/// </summary>
		/// <param name="hwnd">欲为其获取信息的窗口的句柄</param>
		/// <param name="nIndex">
		/// 欲取回的信息，可以是下述任何一个常数：
		/// GWL_EXSTYLE 扩展窗口样式；
		/// GWL_STYLE 窗口样式；
		/// GWL_WNDPROC 该窗口的窗口函数的地址；
		/// GWL_HINSTANCE 拥有窗口的实例的句柄；
		/// GWL_HWNDPARENT 该窗口之父的句柄。不要用SetWindowWord来改变这个值；
		/// GWL_ID 对话框中一个子窗口的标识符；
		/// GWL_USERDATA 含义由应用程序规定；
		/// DWL_DLGPROC 这个窗口的对话框函数地址；
		/// DWL_MSGRESULT 在对话框函数中处理的一条消息返回的值；
		/// DWL_USER 含义由应用程序规定；
		/// </param>
		/// <returns>由nIndex决定。零表示出错。会设置GetLastError</returns>
		[DllImport(DLL)]
		public static extern int GetWindowLong(IntPtr hwnd, int nIndex);

		/// <summary>
		/// 返回指定窗口客户区矩形的大小
		/// </summary>
		/// <param name="hwnd">欲计算大小的目标窗口</param>
		/// <param name="rect">指定一个矩形，用客户区域的大小载入（以像素为单位）</param>
		/// <returns>非零表示成功，零表示失败。会设置GetLastError</returns>
		[DllImport(DLL)]
		public static extern bool GetClientRect(HandleRef hwnd, out RECT rect);
		/// <summary>
		/// 返回指定窗口客户区矩形的大小
		/// </summary>
		/// <param name="hwnd">欲计算大小的目标窗口</param>
		/// <param name="rect">指定一个矩形，用客户区域的大小载入（以像素为单位）</param>
		/// <returns>非零表示成功，零表示失败。会设置GetLastError</returns>
		[DllImport(DLL)]
		public static extern bool GetClientRect(IntPtr hwnd, out RECT rect);

		/// <summary>
		/// 
		/// </summary>
		/// <param name="bVk">keys</param>
		/// <param name="bScan">0</param>
		/// <param name="dwFlags">dwFlags:0=down;2=up</param>
		/// <param name="dwExtraInfo">0</param>
		[DllImport(DLL)]
		public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
		/// <summary>
		/// 
		/// </summary>
		/// <param name="bVk">keys</param>
		/// <param name="bScan">0</param>
		/// <param name="dwFlags">dwFlags:0=down;2=up</param>
		/// <param name="dwExtraInfo">0</param>
		[DllImport(DLL)]
		public static extern void keybd_event(int bVk, uint bScan, uint dwFlags, uint dwExtraInfo);
		/// <summary/>
		[DllImport(DLL)]
		public static extern void mouse_event(MouseEventFlag flags, int dx, int dy, uint data, UIntPtr extraInfo);
		/// <summary/>
		[DllImport(DLL)]
		public static extern void mouse_event(MouseEventFlag flags, int dx, int dy, uint data, uint extraInfo);

		/// <summary/>
		[DllImport(DLL)]
		public static extern int PostMessage(IntPtr hwnd, int msg, IntPtr wParam, uint lParam);
		/// <summary/>
		[DllImport(DLL)]
		public static extern int PostMessage(IntPtr hwnd, int msg, IntPtr wParam, object lParam);
		/// <summary/>
		[DllImport(DLL)]
		public static extern int PostMessage(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam);
		/// <summary/>
		[DllImport(DLL)]
		public static extern int PostMessage(IntPtr hwnd, int msg, int wParam, int lParam);
		/// <summary/>
		[DllImport(DLL)]
		public static extern int PostMessage(IntPtr hwnd, int msg, int wParam, IntPtr lParam);
		/// <summary/>
		[DllImport(DLL)]
		public static extern int PostMessage(HandleRef hwnd, int msg, IntPtr wParam, object lParam);
		/// <summary/>
		[DllImport(DLL)]
		public static extern int PostMessageByNum(HandleRef hwnd, int msg, IntPtr wParam, IntPtr lParam);
		/// <summary/>
		[DllImport(DLL)]
		public static extern int PostMessageByNum(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam);
		/// <summary/>
		[DllImport(DLL)]
		public static extern int PostMessageByString(HandleRef hwnd, int msg, IntPtr wParam, string lParam);
		/// <summary/>
		[DllImport(DLL)]
		public static extern int PostMessageByString(IntPtr hwnd, int msg, IntPtr wParam, string lParam);
		/* lKeyData是用来详细描述按键信息的参数，它是32位的一个数据；
		 * 其中0－15位表示当前按键的次数；
		 * 16-23是表示当前按键的具体扫描码，使用MapVirtualKey转换；
		 * 24位表示当前按下的是否是扩展键，比如ALT和CTRL，或者101/102键盘上的其它键，为1表示是；
		 * 25-28位没有使用，保留；
		 * 29位表示上下文关系，在WM_KEYDOWN消息下始终为0；
		 * 30位表示按键状态，1表示按下，0表示弹起；
		 * 31位表示转变状态，在这个消息下始终为0。
		 * 例Ctrl+A的A弹出消息低位码：1100 0000 0001 1110 0000 0000 0000 0001 (C0 1E 00 01)
		 */

		/// <summary/>
		[DllImport(DLL)]
		public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, StringBuilder lParam);
		/// <summary/>
		[DllImport(DLL)]
		public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, string lParam);
		/// <summary/>
		[DllImport(DLL)]
		public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, uint lParam);
		/// <summary/>
		[DllImport(DLL)]
		public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, int lParam);
		/// <summary/>
		[DllImport(DLL)]
		public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, StringBuilder lParam);
		/// <summary/>
		[DllImport(DLL)]
		public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, string lParam);
		/// <summary/>
		[DllImport(DLL)]
		public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, uint lParam);
		/// <summary/>
		[DllImport(DLL)]
		public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);

		/// <summary/>
		[DllImport(DLL)]
		public static extern uint MapVirtualKey(int wCode, int wMapType);

		/// <summary/>
		[DllImport(DLL)]
		public static extern long SetWindowPos(long hwnd, long hWndInsertAfter, long X, long y, long cx, long cy, long wFlagslong);
		/// <summary/>
		[DllImport(DLL)]
		public static extern long ExitWindowsEx(long uFlags, long dwReserved);

		/// <summary>
		/// 枚举窗口列表中的所有父窗口（顶级和被所有窗口）
		/// </summary>
		/// <param name="lpEnumFunc">指向为每个子窗口都调用的一个函数的指针</param>
		/// <param name="lParam">在枚举期间，传递给dwcbkd32.ocx定制控件之EnumWindows事件的值。这个值的含义是由程序员规定的</param>
		/// <returns>非零表示成功，零表示失败</returns>
		[DllImport(DLL)]
		public static extern bool EnumWindows(EnumWinProc lpEnumFunc, IntPtr lParam);

		[DllImport(DLL)]
		public static extern bool EnumChildWindows(HandleRef hwndParent, EnumWinProc lpEnumFunc, IntPtr lParam);
		[DllImport(DLL)]
		public static extern bool EnumChildWindows(IntPtr hwndParent, EnumWinProc lpEnumFunc, IntPtr lParam);

		/// <summary>
		/// 为指定的窗口取得类名
		/// </summary>
		/// <param name="hwnd">以字节数表示的类名长度；排除最后的空中止字符。零表示出错。会设置GetLastError</param>
		/// <param name="lpClassName">欲获得类名的那个窗口的句柄</param>
		/// <param name="nMaxCount">随同类名载入的缓冲区。预先至少必须分配nMaxCount+1个字符</param>
		/// <returns>由lpClassName提供的缓冲区长度</returns>
		[DllImport(DLL)]
		public static extern int GetClassName(HandleRef hwnd, StringBuilder lpClassName, int nMaxCount);
		/// <summary>
		/// 为指定的窗口取得类名
		/// </summary>
		/// <param name="hwnd">以字节数表示的类名长度；排除最后的空中止字符。零表示出错。会设置GetLastError</param>
		/// <param name="lpClassName">欲获得类名的那个窗口的句柄</param>
		/// <param name="nMaxCount">随同类名载入的缓冲区。预先至少必须分配nMaxCount+1个字符</param>
		/// <returns>由lpClassName提供的缓冲区长度</returns>
		[DllImport(DLL)]
		public static extern IntPtr GetClassName(IntPtr hwnd, StringBuilder lpClassName, int nMaxCount);

		/// <summary>
		/// 获取窗体句柄
		/// </summary>
		/// <param name="hwnd">源窗口句柄</param>
		/// <param name="wCmd">指定结果窗口与源窗口的关系:GW</param>
		/// <returns>窗体句柄</returns>
		[DllImport(DLL)]
		public static extern IntPtr GetWindow(IntPtr hwnd, int wCmd);

		/// <summary/>
		[DllImport(DLL)]
		public static extern int SetParent(IntPtr hwndChild, IntPtr hwndNewParent);

		/// <summary>
		/// 激活指定的窗口
		/// 它可能不会改变输入焦点，所以焦点可能设向一个不活动窗口，最好换用SetFocus函数来激活窗口。如指定的窗口不从属于当前输入线程，则没有任何效果
		/// </summary>
		/// <param name="hwnd">待激活窗口的句柄</param>
		/// <returns>前一个活动窗口的句柄</returns>
		[DllImport(DLL)]
		public static extern IntPtr SetActiveWindow(IntPtr hwnd);

		/// <summary>
		/// 取得一个窗体的标题（caption）文字，或者一个控件的内容（在vb里使用：使用vb窗体或控件的caption或text属性）
		/// </summary>
		/// <param name="hwnd">欲获取文字的那个窗口的句柄</param>
		/// <param name="lpString">预定义的一个缓冲区，至少有cch+1个字符大小；随同窗口文字载入</param>
		/// <param name="cch">lpString缓冲区的长度</param>
		/// <returns>复制到lpString的字串长度；不包括空中止字符。会设置GetLastError</returns>
		[DllImport(DLL)]
		public static extern int GetWindowText(HandleRef hwnd, StringBuilder lpString, int cch);
		/// <summary>
		/// 取得一个窗体的标题（caption）文字，或者一个控件的内容（在vb里使用：使用vb窗体或控件的caption或text属性）
		/// </summary>
		/// <param name="hwnd">欲获取文字的那个窗口的句柄</param>
		/// <param name="lpString">预定义的一个缓冲区，至少有cch+1个字符大小；随同窗口文字载入</param>
		/// <param name="cch">lpString缓冲区的长度</param>
		/// <returns>复制到lpString的字串长度；不包括空中止字符。会设置GetLastError</returns>
		[DllImport(DLL)]
		public static extern int GetWindowText(IntPtr hwnd, StringBuilder lpString, int cch);
		/// <summary/>
		[DllImport(DLL)]
		public static extern int SetWindowText(IntPtr hwnd, StringBuilder lpString);
		/// <summary/>
		[DllImport(DLL)]
		public static extern int SetWindowText(IntPtr hwnd, string lpString);

		/// <summary>
		/// 将输入焦点设到指定的窗口。如有必要，会激活窗口
		/// </summary>
		/// <param name="hwnd">准备接收焦点的窗口的句柄</param>
		/// <returns>前一个拥有焦点的窗口的句柄</returns>
		[DllImport(DLL)]
		public static extern IntPtr SetFocus(IntPtr hwnd);

		/// <summary>
		/// 设置窗口状态和位置信息
		/// </summary>
		/// <param name="hwnd">欲设置位置信息的窗口的句柄</param>
		/// <param name="lpwndpl">窗口的位置与状态信息</param>
		/// <returns>非零表示成功，零表示失败。会设置GetLastError</returns>
		[DllImport(DLL)]
		public static extern bool SetWindowPlacement(IntPtr hwnd, WINDOWPLACEMENT lpwndpl);

		/// <summary/>
		[DllImport(DLL)]
		public static extern int SetMenuItemBitmaps(IntPtr menu, int position, int flags, IntPtr bitmapUnchecked, IntPtr bitmapChecked);

		/// <summary/>
		[DllImport(DLL)]
		public static extern IntPtr GetDesktopWindow();

		/// <summary/>
		[DllImport(DLL)]
		public static extern int EnumThreadWindows(IntPtr dwThreadId, EnumWinProc lpEnumFunc, IntPtr lParam);

		/// <summary/>
		[DllImport(DLL)]
		public static extern int GetWindowThreadProcessId(IntPtr hwnd, ref int lpdwProcessId);

		/// <summary/>
		[DllImport(DLL)]
		public static extern IntPtr GetWindowDC(IntPtr hWnd);

		/// <summary/>
		[DllImport(DLL)]
		public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);

		//为设备信息的删除和插入注册一个窗口 
		[DllImport(DLL, SetLastError = true)]
		public static extern IntPtr RegisterDeviceNotification(IntPtr hwnd, DeviceBroadcastInterface oInterface, uint nFlags);

		//释放上一个函数创建的窗口资源 
		[DllImport(DLL, SetLastError = true)]
		public static extern bool UnregisterDeviceNotification(IntPtr hHandle);

		/// <summary>
		/// 改变指定窗口的位置和大小。顶级窗口可能受最大或最小尺寸的限制，那些尺寸优先于这里设置的参数
		/// </summary>
		/// <param name="hwnd">欲移动窗口的句柄</param>
		/// <param name="x">窗口新的左侧位置</param>
		/// <param name="y">窗口新的顶部位置</param>
		/// <param name="nWidth">窗口的新宽度</param>
		/// <param name="nHeight">窗口的高宽度</param>
		/// <param name="bRepaint">如窗口此时应重画，则设为TRUE（非零）。FALSE（零）则表明应用程序会自己决定是否重画窗口</param>
		/// <returns>非零表示成功，零表示失败</returns>
		[DllImport(DLL)]
		public static extern IntPtr MoveWindow(IntPtr hwnd, int x, int y, int nWidth, int nHeight, int bRepaint);
		/// <summary>
		/// 改变指定窗口的位置和大小。顶级窗口可能受最大或最小尺寸的限制，那些尺寸优先于这里设置的参数
		/// </summary>
		/// <param name="hwnd">欲移动窗口的句柄</param>
		/// <param name="x">窗口新的左侧位置</param>
		/// <param name="y">窗口新的顶部位置</param>
		/// <param name="nWidth">窗口的新宽度</param>
		/// <param name="nHeight">窗口的高宽度</param>
		/// <param name="bRepaint">如窗口此时应重画，则设为TRUE（非零）。FALSE（零）则表明应用程序会自己决定是否重画窗口</param>
		/// <returns>非零表示成功，零表示失败</returns>
		[DllImport(DLL)]
		public static extern IntPtr MoveWindow(IntPtr hwnd, int x, int y, int nWidth, int nHeight, bool bRepaint);

		/// <summary>
		/// 返回包含了指定点的窗口的句柄。忽略屏蔽、隐藏以及透明窗口
		/// </summary>
		/// <param name="xPoint">x点值</param>
		/// <param name="yPoint">y点值</param>
		/// <returns>包含了指定点的窗口的句柄。如指定的点处没有窗口存在，则返回零</returns>
		[DllImport(DLL)]
		public static extern IntPtr WindowFromPoint(int xPoint, int yPoint);

		/// <summary>
		/// 获取鼠标指针的当前位置
		/// </summary>
		/// <param name="lpPoint">随同指针在屏幕像素坐标中的位置载入的一个结构</param>
		/// <returns>非零表示成功，零表示失败。会设置GetLastError</returns>
		[DllImport(DLL)]
		public static extern IntPtr GetCursorPos(out POINT lpPoint);

		[DllImport(DLL)]
		public static extern IntPtr SetWindowRgn(IntPtr hwnd, IntPtr hRgn, bool bRedraw);

		[DllImport(DLL)]
		public static extern IntPtr GetDC(IntPtr hwnd);

		/// <summary>
		/// 将鼠标捕获设置到指定的窗口。在鼠标按钮按下的时候，这个窗口会为当前应用程序或整个系统接收所有鼠标输入
		/// 猜想：与ReleaseCapture函数一起使用，用于判断鼠标离开（mouseleave）事件
		/// </summary>
		/// <param name="hwnd">要接收所有鼠标输入的窗口的句柄</param>
		/// <returns>之前拥有鼠标捕获的窗口的句柄</returns>
		[DllImport(DLL)]
		public static extern IntPtr SetCapture(IntPtr hwnd);

		/// <summary>
		/// 为当前的应用程序释放鼠标捕获
		/// 猜想：与SetCapture函数一起使用，用于判断鼠标离开（mouseleave）事件
		/// </summary>
		/// <returns>TRUE（非零）表示成功，零表示失败</returns>
		[DllImport(DLL)]
		public static extern bool ReleaseCapture();

		/// <summary>
		/// 注册系统热键
		/// </summary>
		/// <param name="hWnd">handle to window</param>
		/// <param name="id">hot key identifier</param>
		/// <param name="keyModifiers">key-modifier options</param>
		/// <param name="vk">virtual-key code, System.Windows.Forms.Keys</param>
		/// <returns></returns>
		[DllImport(DLL)]
		public static extern bool RegisterHotKey(IntPtr hWnd, int id, KeyModifiers keyModifiers, int vk);

		/// <summary>
		/// 取消系统热键
		/// </summary>
		/// <param name="hWnd"></param>
		/// <param name="id"></param>
		/// <returns></returns>
		[DllImport(DLL)]
		public static extern bool UnregisterHotKey(IntPtr hWnd, int id);

		/// <summary>
		/// 将线程输入附加到目标线程
		/// </summary>
		/// <param name="idAttach">要附加的线程</param>
		/// <param name="idAttachTo">被附加的线程</param>
		/// <param name="fAttach">是否附加</param>
		/// <returns></returns>
		[DllImport(DLL, SetLastError = true)]
		public static extern IntPtr AttachThreadInput(IntPtr idAttach, IntPtr idAttachTo, int fAttach);
		/// <summary>
		/// 将线程输入附加到目标线程
		/// </summary>
		/// <param name="idAttach">要附加的线程</param>
		/// <param name="idAttachTo">被附加的线程</param>
		/// <param name="fAttach">是否附加</param>
		/// <returns></returns>
		[DllImport(DLL, SetLastError = true)]
		public static extern IntPtr AttachThreadInput(int idAttach, int idAttachTo, int fAttach);

		/// <summary/>
		[DllImport(DLL)]
		public static extern int DestroyIcon(IntPtr hIcon);

		public static POINT GetCursorPos()
		{
			POINT point;
			User32.GetCursorPos(out point);
			return point;
		}

		public static RECT GetClientRect(IntPtr hwnd)
		{
			RECT rect;
			User32.GetClientRect(hwnd, out rect);
			return rect;
		}

		public static RECT GetWindowRect(IntPtr hwnd)
		{
			RECT rect;
			User32.GetWindowRect(hwnd, out rect);
			return rect;
		}

		public static string GetClassName(IntPtr hwnd)
		{
			var sb = new StringBuilder(byte.MaxValue);
			User32.GetClassName(hwnd, sb, byte.MaxValue);
			return sb.ToString();
		}

		public static string GetWindowText(IntPtr hwnd)
		{
			var sb = new StringBuilder(byte.MaxValue);
			User32.GetWindowText(hwnd, sb, byte.MaxValue);
			return sb.ToString();
		}

		//public static RECT AdjustWindowRect(IntPtr hwnd)
		//{
		//    RECT r0;
		//    User32.GetWindowRect(hwnd, out r0);
		//    RECT r1;
		//    User32.GetClientRect(hwnd, out r1);
		//    int x = User32.GetSystemMetrics(SM.CXFRAME);
		//    int y = User32.GetSystemMetrics(SM.CYFRAME);
		//    int h = User32.GetSystemMetrics(SM.CYCAPTION);
		//    RECT r = new RECT();
		//    r.Top = r0.Top + y + h;
		//    r.Left = r0.Left + x;
		//    r.Bottom = r0.Bottom - y;
		//    r.Right = r0.Right - x;
		//    if (r.Width != r1.Width || r.Height != r1.Height)
		//        throw new Exception("取值出错！");

		//    return r;
		//}

		/// <summary>
		/// lParam
		/// </summary>
		/// <param name="keyScanCode"></param>
		/// <param name="isUp"></param>
		/// <returns></returns>
		public static uint GetVritualKeyLowerParameter(int keyScanCode, bool isUp)
		{
			/* lKeyData是用来详细描述按键信息的参数，它是32位的一个数据；
			 * 其中0－15位表示当前按键的次数；
			 * 16-23是表示当前按键的具体扫描码，使用MapVirtualKey转换；
			 * 24位表示当前按下的是否是扩展键，比如ALT和CTRL，或者101/102键盘上的其它键，为1表示是；
			 * 25-28位没有使用，保留；
			 * 29位表示上下文关系，在WM_KEYDOWN消息下始终为0；
			 * 30位表示按键状态，1表示按下，0表示弹起；
			 * 31位表示转变状态，在这个消息下始终为0。
			 * 例Ctrl+A的A弹出消息低位码：1100 0000 0001 1110 0000 0000 0000 0001 (C0 1E 00 01)
			 */
			const uint I = 1;
			if (isUp)
				return I | User32.MapVirtualKey(keyScanCode, 0) << 16 | I << 30 | I << 31;

			return I | User32.MapVirtualKey(keyScanCode, 0) << 16;
		}

		/// <summary>
		/// 发送键盘消息
		/// </summary>
		/// <param name="value">要发送的字符串，仅限键盘可输入字符。</param>
		/// <returns>成功输入字符数</returns>
		public static int SendKeys(string value)
		{
			return SendKeys(value, false);
		}
		/// <summary>
		/// 发送键盘消息
		/// </summary>
		/// <param name="value">要发送的字符串，仅限键盘可输入字符。</param>
		/// <param name="escape">是否转义</param>
		/// <returns>成功输入字符数</returns>
		public static int SendKeys(string value, bool escape)
		{
			var iR = 0;
			if (string.IsNullOrEmpty(value))
				return iR;

			if (escape)
			{
				value  = value.Replace("{ESC}", ((char)VK.ESCAPE) + string.Empty);
				value  = value.Replace("{TAB}", "\t");
				value  = value.Replace("{ENTER}", Environment.NewLine);
				value  = value.Replace("{HOME}", ((char)VK.HOME) + string.Empty);
				value  = value.Replace("{END}", ((char)VK.END) + string.Empty);
			}
			//if (hwnd != IntPtr.Zero)
			//{
			//    this.ActiveWindow(hwnd);
			//    Thread.Sleep(byte.MaxValue);
			//}
			foreach (char c in value)
				iR += User32.SendKey(c);
			return iR;
		}
		/// <summary>
		/// 发送键盘消息
		/// </summary>
		/// <param name="value">要发送的字符串，仅限键盘可输入字符。</param>
		/// <returns>成功输入字符数</returns>
		public static int SendKey(char value)
		{
			switch (value)
			{
				case '0':
					return User32.SendKey(VK.MAINPAD0, false, false, false, false);
				case ')':
					return User32.SendKey(VK.MAINPAD0, true, false, false, false);

				case '1':
					return User32.SendKey(VK.MAINPAD1, false, false, false, false);
				case '!':
					return User32.SendKey(VK.MAINPAD1, true, false, false, false);

				case '2':
					return User32.SendKey(VK.MAINPAD2, false, false, false, false);
				case '@':
					return User32.SendKey(VK.MAINPAD2, true, false, false, false);

				case '3':
					return User32.SendKey(VK.MAINPAD3, false, false, false, false);
				case '#':
					return User32.SendKey(VK.MAINPAD3, true, false, false, false);

				case '4':
					return User32.SendKey(VK.MAINPAD4, false, false, false, false);
				case '$':
					return User32.SendKey(VK.MAINPAD4, true, false, false, false);

				case '5':
					return User32.SendKey(VK.MAINPAD5, false, false, false, false);
				case '%':
					return User32.SendKey(VK.MAINPAD5, true, false, false, false);

				case '6':
					return User32.SendKey(VK.MAINPAD6, false, false, false, false);
				case '^':
					return User32.SendKey(VK.MAINPAD6, true, false, false, false);

				case '7':
					return User32.SendKey(VK.MAINPAD7, false, false, false, false);
				case '&':
					return User32.SendKey(VK.MAINPAD7, true, false, false, false);

				case '8':
					return User32.SendKey(VK.MAINPAD8, false, false, false, false);
				case '*':
					return User32.SendKey(VK.MAINPAD8, true, false, false, false);

				case '9':
					return User32.SendKey(VK.MAINPAD9, false, false, false, false);
				case '(':
					return User32.SendKey(VK.MAINPAD9, true, false, false, false);

				case ';':
					return User32.SendKey(VK.OEM_1, false, false, false, false);
				case ':':
					return User32.SendKey(VK.OEM_1, true, false, false, false);

				case '=':
					return User32.SendKey(VK.OEM_PLUS, false, false, false, false);
				case '+':
					return User32.SendKey(VK.OEM_PLUS, true, false, false, false);

				case ',':
					return User32.SendKey(VK.OEM_COMMA, false, false, false, false);
				case '<':
					return User32.SendKey(VK.OEM_PLUS, true, false, false, false);

				case '-':
					return User32.SendKey(VK.OEM_MINUS, false, false, false, false);
				case '_':
					return User32.SendKey(VK.OEM_MINUS, true, false, false, false);

				case '.':
					return User32.SendKey(VK.OEM_PERIOD, false, false, false, false);
				case '>':
					return User32.SendKey(VK.OEM_PERIOD, true, false, false, false);

				case '/':
					return User32.SendKey(VK.OEM_2, false, false, false, false);
				case '?':
					return User32.SendKey(VK.OEM_2, true, false, false, false);

				case '`':
					return User32.SendKey(VK.OEM_3, false, false, false, false);
				case '~':
					return User32.SendKey(VK.OEM_3, true, false, false, false);

				case '[':
					return User32.SendKey(VK.OEM_4, false, false, false, false);
				case '{':
					return User32.SendKey(VK.OEM_4, true, false, false, false);

				case '\\':
					return User32.SendKey(VK.OEM_5, false, false, false, false);
				case '|':
					return User32.SendKey(VK.OEM_5, true, false, false, false);

				case ']':
					return User32.SendKey(VK.OEM_6, false, false, false, false);
				case '}':
					return User32.SendKey(VK.OEM_6, true, false, false, false);

				case '\'':
					return User32.SendKey(VK.OEM_7, false, false, false, false);
				case '"':
					return User32.SendKey(VK.OEM_7, true, false, false, false);

				case ' ':
					return User32.SendKey(VK.SPACE, true, false, false, false);
				case '\t':
					return User32.SendKey(VK.TAB, true, false, false, false);
				case '\r':
					return User32.SendKey(VK.RETURN, true, false, false, false);
				case '\n':
					return User32.SendKey(VK.RETURN, true, false, false, false);
				default:
					if (value >= 'A' && value <= 'Z')
					{
						var i = (int)value;
						return User32.SendKey(i, true, false, false, false);
					}
					
					if (value >= 'a' && value <= 'z')
					{
						var t = value.ToString().ToUpper();
						var i = (int)t[0];
						return User32.SendKey(i, false, false, false, false);
					}
					else
					{
						var i = (int)value;
						return User32.SendKey(i, false, false, false, false);
					}
			}
			return 0;
		}
		public static int SendKey(int key, bool shift, bool ctrl, bool alt, bool win)
		{
			if (shift)
			{
				User32.keybd_event(VK.SHIFT, User32.MapVirtualKey(VK.SHIFT, 0), 0x0, 0);
				//User32.keybd_event(VK.LSHIFT, (uint)0, 0x0, 0);
				//User32.keybd_event(VK.SHIFT, (uint)0, 0x0, 0);
				//User32.keybd_event(VK.RSHIFT, (uint)0, 0x0, 0);
				//Thread.Sleep(byte.MaxValue);
			}
			if(ctrl)
				User32.keybd_event(VK.SHIFT, User32.MapVirtualKey(VK.CONTROL, 0), 0x0, 0);
			if(alt)
				User32.keybd_event(VK.SHIFT, User32.MapVirtualKey(VK.MENU, 0), 0x0, 0);
			//if(win)
			//	User32.keybd_event(VK.SHIFT, User32.MapVirtualKey(VK.WIN, 0), 0x0, 0);
			User32.keybd_event(key, User32.MapVirtualKey(key, 0), 0x0, 0);
			//Thread.Sleep(byte.MaxValue);
			User32.keybd_event(key, User32.MapVirtualKey(key, 0), 0x2, 0);
			//Thread.Sleep(byte.MaxValue);
			//if(win)
			//	User32.keybd_event(VK.SHIFT, User32.MapVirtualKey(VK.WIN, 0), 0x2, 0);
			if(alt)
				User32.keybd_event(VK.SHIFT, User32.MapVirtualKey(VK.MENU, 0), 0x2, 0);
			if(ctrl)
				User32.keybd_event(VK.SHIFT, User32.MapVirtualKey(VK.CONTROL, 0), 0x2, 0);
			if (shift)
			{
				User32.keybd_event(VK.SHIFT, User32.MapVirtualKey(VK.SHIFT, 0), 0x2, 0);
				//User32.keybd_event(VK.LSHIFT, (uint)0, 0x2, 0);
				//User32.keybd_event(VK.SHIFT, (uint)0, 0x2, 0);
				//User32.keybd_event(VK.RSHIFT, (uint)0, 0x2, 0);
				//Thread.Sleep(byte.MaxValue);
			}
			return 1;
		}

		public static IntPtr MakLparam(int l, int h)
		{
			h <<= 16;
			l |= h;
			return new IntPtr(l);
		}

		/// <summary>
		/// 取 Progman 类所指的桌面句柄:Progman's first child.
		/// </summary>
		/// <returns>返回 Progman 类所指的桌面句柄</returns>
		public static IntPtr GetDesktop()
		{
			var h = User32.FindWindow("Progman", null);
			if (h == IntPtr.Zero)
				return User32.GetDesktopWindow();

			return User32.GetWindow(h, GW.CHILD);
		}

		public static IntPtr GetLastWindow(IntPtr hParent)
		{
			while (hParent != IntPtr.Zero)
			{
				var h = User32.GetWindow(hParent, GW.CHILD);
				if (h == IntPtr.Zero)
					break;

				hParent = h;
			}
			return hParent;
		}
	}

	/// <summary>
	/// SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, IntPtr threadId)
	/// </summary>
	/// <param name="nCode"></param>
	/// <param name="wParam"></param>
	/// <param name="lParam"></param>
	/// <returns></returns>
	public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);

	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Pack = 1)]
	public struct DeviceBroadcastInterface//public class DeviceBroadcastInterface//
	{
		public int Size;
		public int DeviceType;
		public int Reserved;
		public Guid ClassGuid;
		[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
		public string Name;
	}
}
